#include "KCPMessage.hpp"
#include <arpa/inet.h>
#include <iostream>
#include <unistd.h>

KCPConnection::KCPConnection(uint32_t conv, int sockfd, struct sockaddr_in peer_addr) : sockfd_(sockfd), peer_addr_(peer_addr) {
	kcp_         = ikcp_create(conv, this);
	kcp_->output = KCPConnection::kcp_output;
}

KCPConnection::~KCPConnection() { ikcp_release(kcp_); }

int KCPConnection::kcp_output(const char *buf, int len, ikcpcb *kcp, void *user) {
	KCPConnection *self = static_cast<KCPConnection *>(user);
	return sendto(self->sockfd_, buf, len, 0, (struct sockaddr *) &self->peer_addr_, sizeof(self->peer_addr_));
}

bool KCPConnection::sendMessage(const Message &msg) {
	std::vector<uint8_t> data = msg.serialize();
	int                  ret  = ikcp_send(kcp_, reinterpret_cast<const char *>(data.data()), data.size());
	if (ret < 0) {
		std::cerr << "ikcp_send failed!" << std::endl;
		return false;
	}
	return true;
}

bool KCPConnection::recvMessage(Message &msg) {
	int peek_len = ikcp_peeksize(kcp_);
	if (peek_len < 0) return false;
	std::vector<uint8_t> buf(peek_len);
	int                  recv_len = ikcp_recv(kcp_, reinterpret_cast<char *>(buf.data()), peek_len);
	if (recv_len > 0) {
		msg = Message::deserialize(buf.data(), recv_len);
		return true;
	}
	return false;
}

void KCPConnection::update() { ikcp_update(kcp_, static_cast<IUINT32>(std::clock() * 1000 / CLOCKS_PER_SEC)); }

void KCPConnection::input(const uint8_t *data, int len) { ikcp_input(kcp_, reinterpret_cast<const char *>(data), len); }

uint32_t KCPConnection::check() { return ikcp_check(kcp_, static_cast<IUINT32>(std::clock() * 1000 / CLOCKS_PER_SEC)); }
